﻿
// WinSvrServiceMonitorDlg.cpp: 实现文件
//

#include "pch.h"
#include "framework.h"
#include "WinSvrServiceMonitor.h"
#include "WinSvrServiceMonitorDlg.h"
#include "afxdialogex.h"
#include <iostream>
#include <tchar.h>
#include <Windows.h>
#include <winsvc.h>
using namespace std;
#ifdef _DEBUG
#define new DEBUG_NEW
#endif

#define  WM_SHOWTASK  (WM_USER + 100)
// 用于应用程序“关于”菜单项的 CAboutDlg 对话框

class CAboutDlg : public CDialogEx
{
public:
	CAboutDlg();

// 对话框数据
#ifdef AFX_DESIGN_TIME
	enum { IDD = IDD_ABOUTBOX };
#endif

	protected:
	virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV 支持

// 实现
protected:
	DECLARE_MESSAGE_MAP()
};

CAboutDlg::CAboutDlg() : CDialogEx(IDD_ABOUTBOX)
{
}

void CAboutDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialogEx::DoDataExchange(pDX);
}

BEGIN_MESSAGE_MAP(CAboutDlg, CDialogEx)
END_MESSAGE_MAP()


// CWinSvrServiceMonitorDlg 对话框



CWinSvrServiceMonitorDlg::CWinSvrServiceMonitorDlg(CWnd* pParent /*=nullptr*/)
	: CDialogEx(IDD_WINSVRSERVICEMONITOR_DIALOG, pParent)
	, SvrName(_T(""))
	, MonitorTimeLength(0)
	, MonCount(0)
	, RestartCount(0)
{
	m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
	MonitorTimeLength=120000;
	SvrName=_T("mysql");
	IsMonited = false;
}

void CWinSvrServiceMonitorDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialogEx::DoDataExchange(pDX);
	DDX_Control(pDX, IDC_STATIC_ShowTime, m_lable);
	DDX_Control(pDX, IDC_STATIC_SvrStatus, SvrStatus);
	DDX_Text(pDX, IDC_EDIT1, SvrName);
	DDX_Text(pDX, IDC_EDIT2, MonitorTimeLength);
	DDX_Control(pDX, IDC_STATIC_Moniting, MonMode);
	DDX_Text(pDX, IDC_STATIC_CountInf, MonCount);
	DDX_Text(pDX, IDC_STATIC_CountInf2, RestartCount);
}

BEGIN_MESSAGE_MAP(CWinSvrServiceMonitorDlg, CDialogEx)
	ON_WM_SYSCOMMAND()
	ON_WM_PAINT()
	ON_WM_QUERYDRAGICON()
//	ON_BN_CLICKED(IDOK, &CWinSvrServiceMonitorDlg::OnBnClickedOk)

	ON_WM_TIMER()
	ON_BN_CLICKED(IDCANCEL2, &CWinSvrServiceMonitorDlg::OnBnClickedCancel2)
	ON_MESSAGE(WM_SHOWTASK, OnShowTask)

	ON_WM_SIZE()
	ON_BN_CLICKED(IDC_BUTTON2, &CWinSvrServiceMonitorDlg::OnBnClickedButton2)

	ON_STN_CLICKED(IDC_STATIC_SvrStatus, &CWinSvrServiceMonitorDlg::OnStnClickedStaticSvrstatus)
	ON_COMMAND(ID_32771, &CWinSvrServiceMonitorDlg::On32771)
	ON_COMMAND(ID_32772, &CWinSvrServiceMonitorDlg::On32772)
	ON_STN_CLICKED(IDC_STATIC_CountInf, &CWinSvrServiceMonitorDlg::OnStnClickedStaticCountinf)
	ON_STN_CLICKED(IDC_STATIC_CountInf2, &CWinSvrServiceMonitorDlg::OnStnClickedStaticCountinf2)
END_MESSAGE_MAP()


// CWinSvrServiceMonitorDlg 消息处理程序

BOOL CWinSvrServiceMonitorDlg::OnInitDialog()
{
	CDialogEx::OnInitDialog();

	// 将“关于...”菜单项添加到系统菜单中。

	// IDM_ABOUTBOX 必须在系统命令范围内。
	ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
	ASSERT(IDM_ABOUTBOX < 0xF000);

	CMenu* pSysMenu = GetSystemMenu(FALSE);
	if (pSysMenu != nullptr)
	{
		BOOL bNameValid;
		CString strAboutMenu;
		bNameValid = strAboutMenu.LoadString(IDS_ABOUTBOX);
		ASSERT(bNameValid);
		if (!strAboutMenu.IsEmpty())
		{
			pSysMenu->AppendMenu(MF_SEPARATOR);
			pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
		}
	}

	// 设置此对话框的图标。  当应用程序主窗口不是对话框时，框架将自动
	//  执行此操作
	SetIcon(m_hIcon, TRUE);			// 设置大图标
	SetIcon(m_hIcon, FALSE);		// 设置小图标

	// TODO: 在此添加额外的初始化代码
	m_nid.cbSize = (DWORD)sizeof(NOTIFYICONDATA);

	m_nid.hWnd = this->m_hWnd;

	m_nid.uID = IDR_MAINFRAME;

	m_nid.uFlags = NIF_ICON | NIF_MESSAGE | NIF_TIP;

	m_nid.uCallbackMessage = WM_SHOWTASK;             // 自定义的消息名称

	m_nid.hIcon = LoadIcon(AfxGetInstanceHandle(), MAKEINTRESOURCE(IDI_ICON1));

	CString Tip= _T("服务监控");

	//strcpy(m_nid.szTip, "服务器程序");                // 信息提示条为"服务器程序"，VS2008 UNICODE编码用wcscpy_s()函数
	wcscpy_s(m_nid.szTip, Tip);
	Shell_NotifyIcon(NIM_ADD, &m_nid);                // 在托盘区添加图标

	UpdateData(false);//更新控件的显示内容
	MonMode.SetWindowText(_T("未监控"));
	if (IsMonited)
	{
		GetDlgItem(IDC_BUTTON2)->EnableWindow(false);
		GetDlgItem(IDCANCEL2)->EnableWindow(true);
	}
	else
	{
		GetDlgItem(IDC_BUTTON2)->EnableWindow(true);
		GetDlgItem(IDCANCEL2)->EnableWindow(false);
	}
	SetTimer(2,1000 , NULL);
	return TRUE;  // 除非将焦点设置到控件，否则返回 TRUE
}

void CWinSvrServiceMonitorDlg::OnSysCommand(UINT nID, LPARAM lParam)
{
	if ((nID & 0xFFF0) == IDM_ABOUTBOX)
	{
		CAboutDlg dlgAbout;
		dlgAbout.DoModal();
	}
	else
	{
		CDialogEx::OnSysCommand(nID, lParam);
	}
}

// 如果向对话框添加最小化按钮，则需要下面的代码
//  来绘制该图标。  对于使用文档/视图模型的 MFC 应用程序，
//  这将由框架自动完成。

void CWinSvrServiceMonitorDlg::OnPaint()
{
	if (IsIconic())
	{
		CPaintDC dc(this); // 用于绘制的设备上下文

		SendMessage(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(dc.GetSafeHdc()), 0);

		// 使图标在工作区矩形中居中
		int cxIcon = GetSystemMetrics(SM_CXICON);
		int cyIcon = GetSystemMetrics(SM_CYICON);
		CRect rect;
		GetClientRect(&rect);
		int x = (rect.Width() - cxIcon + 1) / 2;
		int y = (rect.Height() - cyIcon + 1) / 2;

		// 绘制图标
		dc.DrawIcon(x, y, m_hIcon);
	}
	else
	{
		CDialogEx::OnPaint();
	}
}

//当用户拖动最小化窗口时系统调用此函数取得光标
//显示。
HCURSOR CWinSvrServiceMonitorDlg::OnQueryDragIcon()
{
	return static_cast<HCURSOR>(m_hIcon);
}

//void CWinSvrServiceMonitorDlg::OnBnClickedOk()
//{
	// TODO: 在此添加控件通知处理程序代码
//	CDialogEx::OnOK();
//}

void CWinSvrServiceMonitorDlg::OnTimer(UINT_PTR nIDEvent)
{
	// TODO: 在此添加消息处理程序代码和/或调用默认值
	if (nIDEvent == 1) {
		MonCount++;
		UpdateData(false);//更新控件的显示内容
		MonitorMysqlService();
	}
	if (nIDEvent == 2) {
		CTime now = CTime::GetCurrentTime();
		CString str = now.Format(L"%Y-%m-%d %H:%M:%S");
		m_lable.SetWindowText(str);		
	}

	CDialogEx::OnTimer(nIDEvent);
}

void CWinSvrServiceMonitorDlg::MonitorMysqlService()
{
	CString strCommand;
	strCommand.Format(_T("/c net start %s"), SvrName);
	CString SvrStatusStr;
	//TCHAR szSvcName[] = _T("AutoWorkSrv");
	SC_HANDLE schSCManager = NULL;
	SC_HANDLE schService = NULL;

	SERVICE_STATUS_PROCESS ssStatus;
	DWORD dwOldCheckPoint;
	DWORD dwStartTickCount;
	DWORD dwWaitTime;
	DWORD dwBytesNeeded;

	// Get a handle to the SCM database.

	schSCManager = OpenSCManager(
		NULL,                                // local computer
		NULL,                                // ServicesActive database
		SC_MANAGER_ALL_ACCESS);              // full access rights

	if (NULL == schSCManager)
	{
		printf("OpenSCManager failed (%d)\n", GetLastError());

	}

	// Get a handle to the service.

	schService = OpenService(
		schSCManager,                      // SCM database
		SvrName,                         // name of service
		SERVICE_QUERY_STATUS |
		SERVICE_ENUMERATE_DEPENDENTS);     // full access

	if (schService == NULL)
	{
		printf("OpenService failed (%d)\n", GetLastError());
		CloseServiceHandle(schSCManager);
		SvrStatusStr.Format(_T("%s服务异常!"), SvrName);
		SvrStatus.SetWindowText(SvrStatusStr);

	}

	// Check the status in case the service is not stopped.

	if (!QueryServiceStatusEx(
		schService,                         // handle to service
		SC_STATUS_PROCESS_INFO,             // information level
		(LPBYTE)&ssStatus,                 // address of structure
		sizeof(SERVICE_STATUS_PROCESS),     // size of structure
		&dwBytesNeeded))                  // size needed if buffer is too small
	{
		printf("QueryServiceStatusEx failed (%d)\n", GetLastError());
		CloseServiceHandle(schService);
		CloseServiceHandle(schSCManager);
		SvrStatusStr.Format(_T("%s服务异常!"), SvrName);
		SvrStatus.SetWindowText(SvrStatusStr);
	}
	else
	{
		// Check if the service is already running. It would be possible
		// to stop the service here, but for simplicity this example just returns.
		printf("Service status: ");
		switch (ssStatus.dwCurrentState)
		{
		case SERVICE_STOPPED:
		case SERVICE_STOP_PENDING:
			//printf("Stop");			
			SvrStatusStr.Format(_T("%s服务已停止!"), SvrName);
			SvrStatus.SetWindowText(SvrStatusStr);
			//重新启动指定的服务
			ShellExecute(NULL, _T("open"), _T("cmd"), strCommand, NULL, SW_SHOW);
			RestartCount++;
			UpdateData(false);//更新控件的显示内容
			//GetDlgItem(IDC_STATIC_SvrStatus)->SetWindowTextW()
			break;
		case SERVICE_PAUSED:
		case SERVICE_PAUSE_PENDING:
			//printf("Pause");
			SvrStatusStr.Format(_T("%s服务暂停中!"), SvrName);
			SvrStatus.SetWindowText(SvrStatusStr);
			break;
		case SERVICE_CONTINUE_PENDING:
		case SERVICE_RUNNING:
		case SERVICE_START_PENDING:
			//printf("Running");			
			SvrStatusStr.Format(_T("%s服务正在运行!"), SvrName);
			SvrStatus.SetWindowText(SvrStatusStr);
			break;
		}
		cout << endl;
	}
	cin.get();
}

void CWinSvrServiceMonitorDlg::OnBnClickedCancel2()
{
	// TODO: 在此添加控件通知处理程序代码
	KillTimer(1);
	MonMode.SetWindowText(_T("未监控"));
	IsMonited = false;
	if (!IsMonited)
	{
		GetDlgItem(IDC_BUTTON2)->EnableWindow(true);
		GetDlgItem(IDCANCEL2)->EnableWindow(false);
	}
}

LRESULT CWinSvrServiceMonitorDlg::OnShowTask(WPARAM wParam, LPARAM lParam)

{
	if (wParam != IDR_MAINFRAME)
		return 1;
	switch (lParam)
	{
	case WM_RBUTTONUP:                                        // 右键起来时弹出菜单
	{
		POINT pt;
		CMenu menu; //定义右键菜单对象 
		GetCursorPos(&pt); //获取当前鼠标位置 
		menu.LoadMenu(IDR_MENU1); //载入右键快捷菜单 
		SetForegroundWindow();//放置在前面 
		CMenu* pmenu; //定义右键菜单指针 
		pmenu = menu.GetSubMenu(0); //该函数取得被指定菜单激活的下拉式菜单或子菜单的句柄
		ASSERT(pmenu != NULL);
		pmenu->TrackPopupMenu(TPM_RIGHTBUTTON | TPM_LEFTALIGN, pt.x, pt.y, this); //在指定位置显示右键快捷菜单 
		HMENU hmenu = pmenu->Detach();
		pmenu->DestroyMenu();
	}
	break;
	case WM_LBUTTONDBLCLK:                                 // 双击左键的处理
	{
		this->ShowWindow(SW_SHOWNORMAL);         // 显示主窗口
	}
	break;
	}

	return 0;

}

void CWinSvrServiceMonitorDlg::OnSize(UINT nType, int cx, int cy)
{
	CDialogEx::OnSize(nType, cx, cy);

	// TODO: 在此处添加消息处理程序代码
	if (nType == SIZE_MINIMIZED)

	{
		ShowWindow(SW_HIDE); // 当最小化市，隐藏主窗口     
	}
}


BOOL CWinSvrServiceMonitorDlg::DestroyWindow()
{
	// TODO: 在此添加专用代码和/或调用基类
	Shell_NotifyIcon(NIM_DELETE, &m_nid);
	return CDialogEx::DestroyWindow();
}


void CWinSvrServiceMonitorDlg::OnBnClickedButton2()
{
	// TODO: 在此添加控件通知处理程序代码
	CTime now = CTime::GetCurrentTime();
	CString str = now.Format(L"%Y-%m-%d %H:%M:%S");
	m_lable.SetWindowText(str);
	UpdateData(true);//从控件内容更新变量值
	MonitorMysqlService();
	SetTimer(1, MonitorTimeLength, NULL);
	MonMode.SetWindowText(_T("监控中"));
	MonCount++;
	UpdateData(false);//更新控件的显示内容
	IsMonited = true;
	if (IsMonited)
	{
		GetDlgItem(IDC_BUTTON2)->EnableWindow(false);
		GetDlgItem(IDCANCEL2)->EnableWindow(true);
	}
}


//void CWinSvrServiceMonitorDlg::OnBnClickedCancel()
//{
	// TODO: 在此添加控件通知处理程序代码
//	CDialogEx::OnCancel();
//}


void CWinSvrServiceMonitorDlg::OnStnClickedStaticSvrstatus()
{
	// TODO: 在此添加控件通知处理程序代码
}

void CWinSvrServiceMonitorDlg::OnCancel()
{
	ShowWindow(SW_HIDE);
	ShowBalloonTip(_T("程序已最小化到托盘"), _T("提示"), 3000, 1);
}

bool CWinSvrServiceMonitorDlg::ShowBalloonTip(LPCTSTR szMsg, LPCTSTR szTitle, UINT uTimeout, DWORD dwInfoFlags)
{
	m_nid.cbSize = sizeof(NOTIFYICONDATA);
	m_nid.uFlags = NIF_INFO;
	m_nid.uTimeout = uTimeout;
	m_nid.dwInfoFlags = dwInfoFlags;
	wcscpy_s(m_nid.szInfo, szMsg ? szMsg : _T(""));
	wcscpy_s(m_nid.szInfoTitle, szTitle ? szTitle : _T(""));
	return Shell_NotifyIcon(NIM_MODIFY, &m_nid);
}


void CWinSvrServiceMonitorDlg::On32771()
{
	// TODO: 在此添加命令处理程序代码
	CDialogEx::OnOK();
}


void CWinSvrServiceMonitorDlg::On32772()
{
	// TODO: 在此添加命令处理程序代码
	CAboutDlg dlg;
	dlg.DoModal();
}


void CWinSvrServiceMonitorDlg::OnStnClickedStaticCountinf()
{
	// TODO: 在此添加控件通知处理程序代码
}


void CWinSvrServiceMonitorDlg::OnStnClickedStaticCountinf2()
{
	// TODO: 在此添加控件通知处理程序代码
}
